package org.tq.anchors;

import android.os.Handler;
import android.os.Looper;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ExecutorManager {

    private static ThreadPoolExecutor cpuExecutor;
    private static ExecutorService ioExecutor;
    private static Executor mainExecutor;

    private static int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 5));
    private static int MAX_POOL_SIZE = CORE_POOL_SIZE;
    private static long KEEP_ALIVE_TIME = 5L;

    private static RejectedExecutionHandler handler = (runnable, threadPoolExecutor) -> Executors.newCachedThreadPool(Executors.defaultThreadFactory());

    public static ThreadPoolExecutor getCpuExecutor() {
        cpuExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
                MAX_POOL_SIZE,
                KEEP_ALIVE_TIME,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(),
                Executors.defaultThreadFactory(),
                handler);
        cpuExecutor.allowCoreThreadTimeOut(true);
        return cpuExecutor;
    }

    public static ExecutorService getIoExecutor() {
        ioExecutor = Executors.newCachedThreadPool(Executors.defaultThreadFactory());
        return ioExecutor;
    }

    public static Executor getMainExecutor() {
        mainExecutor = new Executor() {
            private Handler handler = new Handler(Looper.getMainLooper());

            @Override
            public void execute(Runnable runnable) {
                handler.post(runnable);
            }
        };
        return mainExecutor;
    }
}
